// 引入其他类
// 导入食物类
import Food from './Food'
// 导入 记分牌类
import ScopeBoard from './ScoreBoard'
// 导入蛇类
import Snake from './Snake'

// 游戏控制器，控制所有的类
export default class GameController {
    // 定义三个属性：蛇，食物，记分牌
    private snake: Snake;
    private food: Food;
    private scopeBoard: ScopeBoard;
    // 创建属性来存储移动方向（按键值）
    private direction: string = '';
    // 创建属性记录当前游戏是否结束(默认情况下表示活着，游戏未结束)
    private isLive: boolean = true;
    // 存储初始化方法
    gameInit: any;

    constructor() {
        this.snake = new Snake();
        this.food = new Food();
        this.scopeBoard = new ScopeBoard();
        // 定义初始化方法（开始游戏）
        this.init()
    }
    // 初始化方法
    init() {
        /// 绑定键盘按下的事件
        // .bind(this) 修改this指向为GameController对象
        // document.addEventListener('keydown', this.keydownHandler.bind(this))
        // 调用run方法，蛇进行移动，方法需要持续调用
        // 在run方法里的最后用了一个setTimeOut函数来调用自己（run方法），所以这个方法会一直自动执行
        this.run();  // 此时只会调用一次
        document.addEventListener('keydown', this.keydownHandler.bind(this))

    }

    // 键盘按下的相应函数
    /* 
        chrome浏览器：上右下左 ArrowUp、ArrowRight、ArrowDown、ArrowLeft
        ie浏览器：上右下左 Up、Down、Left、Right
    */
    // e: KeyboardEvent 传入按键参数
    private keydownHandler(event: KeyboardEvent) {
        // console.log(e.key);
        // 用direction存储用户按下的键值
        // console.log(this); // 此时this指向document

        // 赋值之前要校验用户按下的是否为方向键
        this.direction = event.key;



    }

    // 控制蛇移动的方法
    run() {
        // 根据方向direction，蛇进行相应的位置改变
        /**
         * 向上： top减少
         * 向下： top增加
         * 向左： left减少
         * 向右： left增加
         */
        // 获取蛇的当前坐标
        let X = this.snake.X;
        let Y = this.snake.Y;
        // 修改 X/Y
        switch (this.direction) {
            case 'ArrowUp':
                // 向上移动 top减少
                Y -= 10;
                break;
            case 'Up':
                // 向上移动 top减少
                Y -= 10;
                break;
            case 'ArrowDown':
                // 向下移动 top增加
                Y += 10;
                break;
            case 'Down':
                // 向下移动 top增加
                Y += 10;
                break;
            case 'ArrowLeft':
                // 向左移动 left减少
                X -= 10;
                break;
            case 'Left':
                // 向左移动 left减少
                X -= 10;
                break;
            case 'ArrowRight':
                // 向右移动 left增加
                X += 10;
                break;
            case 'Right':
                // 向右移动 left增加
                X += 10;
                break;
            default:
                break;
        }

        // 判断蛇是否吃到了食物
        this.checkEat(X, Y);

        // // 修改蛇X/Y的值
        // this.snake.X = X;
        // this.snake.Y = Y;
        // 使用try catch捕获异常  修改蛇X/Y的值
        // 修改蛇的坐标
        try {
            this.snake.X = X;
            this.snake.Y = Y;
        } catch (error: any) {
            // 出现异常 游戏结束
            console.log(error);
            alert(error.message + 'GAME OVER!')
            this.isLive = false;
        }

        // 开启定时调用，每隔300ms调用一次run方法
        // 等级越高，执行速度越快，蛇的运行速度越快
        // 游戏未结束才会执行蛇的移动
        this.isLive && setTimeout(this.run.bind(this), 300 - (this.scopeBoard.level - 1) * 30)


    }

    // 是否吃到食物的方法
    checkEat(X: number, Y: number): void {
        // 吃到食物了
        if (X === this.food.X && Y === this.food.Y) {
            // 食物位置重置
            this.food.change();
            // 分数增加
            this.scopeBoard.addScore()
            // 蛇身体增加
            this.snake.addBody()
        }
    }

}